package cn.iocoder.yudao.module.infra.controller.admin.infotablecollect;

import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenDetailRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
import cn.iocoder.yudao.module.infra.convert.infocolumncollect.InfoColumnCollectConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.infocolumncollect.InfoColumnCollectDO;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;

import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

import cn.iocoder.yudao.module.infra.controller.admin.infotablecollect.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.infotablecollect.InfoTableCollectDO;
import cn.iocoder.yudao.module.infra.convert.infotablecollect.InfoTableCollectConvert;
import cn.iocoder.yudao.module.infra.service.infotablecollect.InfoTableCollectService;

@Tag(name = "管理后台 - 基础资料表汇总")
@RestController
@RequestMapping("/infra/info-table-collect")
@Validated
public class InfoTableCollectController {

    @Resource
    private InfoTableCollectService infoTableCollectService;

    @PostMapping("/create")
    @Operation(summary = "创建基础资料表汇总")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:create')")
    public CommonResult<Long> createInfoTableCollect(@Valid @RequestBody InfoTableCollectCreateReqVO createReqVO) {
        return success(infoTableCollectService.createInfoTableCollect(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新基础资料表汇总")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:update')")
    public CommonResult<Boolean> updateInfoTableCollect(@Valid @RequestBody InfoTableCollectUpdateReqVO updateReqVO) {
        infoTableCollectService.updateInfoTableCollect(updateReqVO);
        return success(true);
    }

    @Operation(summary = "删除数据库的表和字段定义")
    @DeleteMapping("/delete")
    @Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:delete')")
    public CommonResult<Boolean> deleteCodegen(@RequestParam("tableId") Long tableId) {
        infoTableCollectService.deleteCodegen(tableId);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得基础资料表汇总")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:query')")
    public CommonResult<InfoTableCollectRespVO> getInfoTableCollect(@RequestParam("id") Long id) {
        InfoTableCollectDO infoTableCollect = infoTableCollectService.getInfoTableCollect(id);
        return success(InfoTableCollectConvert.INSTANCE.convert(infoTableCollect));
    }

    @GetMapping("/getByTableName")
    @Operation(summary = "根据表名获取表元素")
    @Parameter(name = "tableName", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:query')")
    public CommonResult<InfoTableCollectRespVO> getByTableName(@RequestParam("tableName") String tableName) {
        InfoTableCollectDO infoTableCollect = infoTableCollectService.getByTableName(tableName);
        return success(InfoTableCollectConvert.INSTANCE.convert(infoTableCollect));
    }

    @GetMapping("/list")
    @Operation(summary = "获得基础资料表汇总列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:query')")
    public CommonResult<List<InfoTableCollectRespVO>> getInfoTableCollectList(@RequestParam("ids") Collection<Long> ids) {
        List<InfoTableCollectDO> list = infoTableCollectService.getInfoTableCollectList(ids);
        return success(InfoTableCollectConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/page")
    @Operation(summary = "获得表定义分页")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:query')")
    public CommonResult<PageResult<InfoTableCollectRespVO>> getInfoTableCollectPage(@Valid InfoTableCollectPageReqVO pageVO) {
        PageResult<InfoTableCollectDO> pageResult = infoTableCollectService.getInfoTableCollectPage(pageVO);
        return success(InfoTableCollectConvert.INSTANCE.convertPage(pageResult));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出基础资料表汇总 Excel")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:export')")
    @OperateLog(type = EXPORT)
    public void exportInfoTableCollectExcel(@Valid InfoTableCollectExportReqVO exportReqVO,
              HttpServletResponse response) throws IOException {
        List<InfoTableCollectDO> list = infoTableCollectService.getInfoTableCollectList(exportReqVO);
        // 导出 Excel
        List<InfoTableCollectExcelVO> datas = InfoTableCollectConvert.INSTANCE.convertList02(list);
        ExcelUtils.write(response, "基础资料表汇总.xls", "数据", InfoTableCollectExcelVO.class, datas);
    }

    @Operation(summary = "基于数据库的表结构，创建代码生成器的表和字段定义")
    @PostMapping("/create-list")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:create')")
    public CommonResult<List<Long>> createCodegenList(@Valid @RequestBody CodegenCreateListReqVO reqVO) {
        return success(infoTableCollectService.createCodegenList(getLoginUserId(), reqVO));
    }

    @GetMapping("/db/table/list")
    @Operation(summary = "获得数据库自带的表定义列表", description = "会过滤掉已经导入 Codegen 的表")
    @Parameters({
            @Parameter(name = "dataSourceConfigId", description = "数据源配置的编号", required = true, example = "1"),
            @Parameter(name = "name", description = "表名，模糊匹配", example = "yudao"),
            @Parameter(name = "comment", description = "描述，模糊匹配", example = "芋道")
    })

    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:query')")
    public CommonResult<List<DatabaseTableRespVO>> getDatabaseTableList(
            @RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "comment", required = false) String comment) {
        return success(infoTableCollectService.getDatabaseTableList(dataSourceConfigId, name, comment));
    }

    @GetMapping("/detail")
    @Operation(summary = "获得表和字段的明细")
    @Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('infra:info-table-collect:query')")
    public CommonResult<InfoTCDetailRespVO> getCodegenDetail(@RequestParam("tableId") Long tableId) {
        InfoTableCollectDO table = infoTableCollectService.getInfoTableCollect(tableId);
        List<InfoColumnCollectDO> columns = infoTableCollectService.getInfoColumnCollectListByTableId(tableId);
        // 拼装返回
        return success(InfoColumnCollectConvert.INSTANCE.convert(table, columns));
    }

}
